import type { PalletStatus, PoIType } from '@/typings'
import ROSLIB from 'roslib'
import { ros } from './ros'

type PreviewMap = {
  map_name: string
  preview_image: string
}

type PoIMapType = {
  ret: boolean
  poi_map: {
    pois: PoIType[]
  }
}

export function getPoIMap () {
  const service = new ROSLIB.Service<ROSLIB.ServiceRequest, PoIMapType>({
    ros,
    name: '/get_poimap',
    serviceType: 'api_srvs/GetPoIMap',
  })

  return new Promise<PoIMapType>((resolve, reject) => {
    service.callService(
      new ROSLIB.ServiceRequest({}),
      resp => {
        resolve(resp)
      },
      error => {
        reject(error)
      },
    )
  })
}

export function getPalletMapStatus (req: { map_name: string }) {
  const service = new ROSLIB.Service<
    ROSLIB.ServiceRequest,
    { ret: boolean, pallet_status: PalletStatus[] }
  >({
    ros,
    name: '/get_appmgr_pallet_map_status',
    serviceType: 'api_srvs/GetPalletMapStatus',
  })

  return new Promise<{ ret: boolean, pallet_status: PalletStatus[] }>(
    (resolve, reject) => {
      service.callService(
        new ROSLIB.ServiceRequest(req),
        resp => {
          resolve(resp)
        },
        error => {
          reject(error)
        },
      )
    },
  )
}

export function setPalletMapStatus (req: {
  map_name: string
  pallet_status: {
    pallet_id: number
    pallet_status: number
    goods_name: string
  }
}) {
  const service = new ROSLIB.Service<ROSLIB.ServiceRequest, { ret: boolean }>({
    ros,
    name: '/update_appmgr_pallet_status',
    serviceType: 'api_srvs/SetPalletStatus',
  })

  return new Promise<{ ret: boolean }>((resolve, reject) => {
    service.callService(
      new ROSLIB.ServiceRequest(req),
      resp => {
        resolve(resp)
      },
      error => {
        reject(error)
      },
    )
  })
}

type GetMapNamesResponse = {
  map_name_list: {
    default_map_name: string
    map_names: string[]
    preview_map: PreviewMap[]
  }
  ret: boolean
}

export function getMapNames () {
  const service = new ROSLIB.Service<
    ROSLIB.ServiceRequest,
    GetMapNamesResponse
  >({
    ros,
    name: '/get_mapnames',
    serviceType: 'api_srvs/GetMapNames',
  })

  return new Promise<GetMapNamesResponse>((resolve, reject) => {
    service.callService(
      new ROSLIB.ServiceRequest({}),
      resp => {
        resolve(resp)
      },
      error => {
        reject(error)
      },
    )
  })
}

/**
 * 使用Ros中的服务调用，用于向 /mission_navigate_srv 的服务发送请求
 * 执行不同类型的任务导航
 */
type MissionNavigateRequest = {
  cmd: {
    func_type: number
    mission_type: number
    motion_type: number
    loop_num: number
    poi_array: {
      pois: any
    }
  }
}

export function missionNavigate (req: MissionNavigateRequest) {
  const service = new ROSLIB.Service<ROSLIB.ServiceRequest, { ret: boolean }>({
    ros,
    name: '/mission_navigate_srv',
    serviceType: 'api_srvs/MissionNavigate',
  })

  return new Promise<{ ret: boolean }>((resolve, reject) => {
    service.callService(
      new ROSLIB.ServiceRequest(req),
      resp => {
        resolve(resp)
      },
      error => {
        reject(error)
      },
    )
  })
}

/**
 * 使用Ros中的服务调用，用于向 /goal_navigate_srv 的服务发送请求
 * 请求开始导航（定点导航）
 */
type GoalNavigateRequest = {
  cmd: {
    func_type: number
    nav_mode: number
    goal_pose: {
      x: number
      y: number
      theta: number
    }
  }
}
export function goalNavigate (req: GoalNavigateRequest) {
  const service = new ROSLIB.Service<ROSLIB.ServiceRequest, { ret: boolean }>({
    ros,
    name: '/goal_navigate_srv',
    serviceType: 'api_srvs/GoalNavigate',
  })

  return new Promise<{ ret: boolean }>((resolve, reject) => {
    service.callService(
      new ROSLIB.ServiceRequest(req),
      resp => {
        resolve(resp)
      },
      error => {
        reject(error)
      },
    )
  })
}
